package com.flyqiu.flow.api.service;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.flyqiu.flow.bpmn.FlyQiuBpmModeler;
import com.flyqiu.flow.common.enums.ProcDefStatus;
import com.flyqiu.flow.common.enums.ProcDeployType;
import com.flyqiu.flow.model.entity.ProcDeployDef;
import com.flyqiu.flow.model.entity.ProcModel;
import com.flyqiu.flow.model.entity.base.FlowBaseDao;

import java.util.List;

public interface FlowModelService {
    /**
     * 创建模型
     *
     * @return
     */
    default ProcModel createModel() {
        return new ProcModel();
    }

    /**
     * 保存模型
     *
     * @param model
     */
    void saveModel(ProcModel model);

    /**
     * 删除模型
     *
     * @param modelId
     */
    void deleteModel(String modelId);

    /**
     * 查询流程模型
     *
     * @param wrapper
     * @return
     */
    List<ProcModel> listProcModel(Wrapper<ProcModel> wrapper);

    /**
     * 分页查询流程模型
     *
     * @param page
     * @param wrapper
     * @return
     */
    Page<ProcModel> pageProcModel(Page<ProcModel> page, Wrapper<ProcModel> wrapper);

    /**
     * 获取流程模型数量
     *
     * @param wrapper
     * @return
     */
    long countProcModel(Wrapper<ProcModel> wrapper);

    /**
     * 根据模型id获取模型
     *
     * @param modelId
     * @return
     */
    default ProcModel getProcModel(String modelId) {
        LambdaQueryWrapper<ProcModel> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProcModel::getId, modelId);
        return getProcModel(wrapper);
    }

    /**
     * 获取模型
     *
     * @param wrapper
     * @return
     */
    ProcModel getProcModel(Wrapper<ProcModel> wrapper);

    void saveModelEditorSource(String modelSource, String currentFormat);

    /**
     * 发布流程
     *
     * @param source
     */
    default void saveModelEditorSource(JSONObject source) {
        String defKey = source.getString(FlyQiuBpmModeler.PROC_MAIN_DEF_KEY);
        saveModelEditorSource(defKey, source);
    }

    /**
     * 保存流程模型资源
     *
     * @param modeKey
     * @param source
     */
    void saveModelEditorSource(String modeKey, JSONObject source);


    /**
     * 保存流程模型资源
     *
     * @param modeKey
     * @return
     */
    JSONObject getModelEditorSource(String modeKey);

    /**
     * 获取模型配置
     *
     * @param modeKey      模型key
     * @param targetFormat 目标格式
     * @return 返回目标格式的模型资源
     */
    String getModelEditorSource(String modeKey, String targetFormat);


    /**
     * 部署流程
     *
     * @param modelId 模型id
     * @return {@linkplain ProcDeployDef 流程发布定义信息}
     */
    ProcDeployDef deployModel(String modelId);


    /**
     * 部署流程
     *
     * @param modelId
     * @param procDefKey
     * @return
     */
    default ProcDeployDef deployModel(String modelId, String procDefKey) {
        return deployModel(modelId, procDefKey, procDefKey);
    }

    /**
     * 部署流程
     *
     * @param modelId    模型id
     * @param procDefKey 流程定义key
     * @param procName   模型名称
     * @return {@link ProcDeployDef }{@linkplain }
     */
    default ProcDeployDef deployModel(String modelId, String procDefKey, String procName) {
        return deployModel(modelId, procDefKey, procName, null);
    }

    /**
     * 部署流程
     *
     * @param modelId
     * @param procDefKey
     * @param procName
     * @param category
     * @return
     */
    ProcDeployDef deployModel(String modelId, String procDefKey, String procName, String category);

    /**
     * 部署流程
     *
     * @param modelSource
     * @param procDefKey
     * @param procName
     * @param category
     * @return
     */
    ProcDeployDef deployModel(JSONObject modelSource, String procDefKey, String procName, String category);

    /**
     * 部署流程
     *
     * @param modelSource
     * @param procDeployType
     * @param procDefKey
     * @param procName
     * @param category
     * @return
     */
    default ProcDeployDef deployModel(JSONObject modelSource, ProcDeployType procDeployType, String procDefKey, String procName, String category) {
        return deployModel(modelSource, procDeployType.getValue(), procDefKey, procName, category);
    }

    /**
     * 部署流程模型
     *
     * @param modelSource
     * @param procExecuteType
     * @param procDefKey
     * @param procName
     * @param category
     * @return
     */
    ProcDeployDef deployModel(JSONObject modelSource, String procExecuteType, String procDefKey, String procName, String category);

    /**
     * 修改流程定义状态
     *
     * @param deployDefId   流程定义id
     * @param procDefStatus 流程定义状态
     */
    void updateDeployDefStatus(String deployDefId, ProcDefStatus procDefStatus);

    /**
     * 查询最新版本的流程定义部署
     *
     * @param procDeployDefKey
     * @return
     */
    default ProcDeployDef lastVersionProcDeployDef(String procDeployDefKey) {
        return lastVersionProcDeployDef(procDeployDefKey, null);
    }

    /**
     * 查询最新版本的流程定义部署
     *
     * @param procDeployDefKey
     * @param tenantId
     * @return
     */
    ProcDeployDef lastVersionProcDeployDef(String procDeployDefKey, String tenantId);

    /**
     * 根据条件查询流程部署
     *
     * @param wrapper
     * @return
     */
    List<ProcDeployDef> listProcDeploy(Wrapper<ProcDeployDef> wrapper);

    /**
     * 分页查询已部署流程
     *
     * @param page    分页信息
     * @param wrapper 查询条件
     * @return {@link  ProcDeployDef} 流程部署信息
     */
    Page<ProcDeployDef> pageProcDeploy(Page<ProcDeployDef> page, Wrapper<ProcDeployDef> wrapper);

    long countProcDeploy(Wrapper<ProcDeployDef> wrapper);

    /**
     * 根据发布id 删除发布的模型
     *
     * @param deployId 发布定义id
     */
    void deleteDeploy(String deployId);

    /**
     * 根据流程部署定义id 获取流程部署定义
     *
     * @param deployId 流程部署id
     * @return
     */
    default ProcDeployDef getProcDeployDef(String deployId) {
        LambdaQueryWrapper<ProcDeployDef> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FlowBaseDao::getId, deployId);
        return getProcDeployDef(queryWrapper);
    }

    /**
     * 获取发布定义信息
     *
     * @param wrapper
     * @return
     */
    ProcDeployDef getProcDeployDef(Wrapper<ProcDeployDef> wrapper);

    /**
     * 获取流程模型资源信息
     *
     * @param procDeployDefId
     * @return {@link FlyQiuBpmModeler}
     */
    FlyQiuBpmModeler getBpmModeler(String procDeployDefId);

    /**
     * 获取流程模型资源信息
     *
     * @param procDeployDefId 模型发布定义id
     * @param targetFormat    目标格式
     * @return {@link String} 返回目标格式的模型资源字符串
     */
    String getBpmModeler(String procDeployDefId, String targetFormat);

}
